package oss.ngocminh.fw;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;

import oss.ngocminh.fw.dao.DatabaseHelper;
import oss.ngocminh.fw.dao.SubscriptionDAO;
import oss.ngocminh.fw.dao.ThreadDAO;
import oss.ngocminh.fw.data.Post;
import oss.ngocminh.fw.data.Subscription;
import oss.ngocminh.fw.forum.ForumAdapter;
import oss.ngocminh.fw.forum.PostLoadingCallback;
import oss.ngocminh.fw.forum.VBulettin;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class ForumWatcherActivity extends Activity {
	
	private static final int CREATE_FIRST_SUBSCRIPTION = 1;
	private ForumAdapter forumAdapter = new VBulettin();
	private DatabaseHelper db = new DatabaseHelper(this);
	private SubscriptionDAO subscriptionDAO = new SubscriptionDAO(db);
	private ThreadDAO threadDAO = new ThreadDAO(db);
	
	private Subscription subscription;
	private int firstPage = -1;
	
	private LinearLayout pnlPosts;
	private String lastPostId;
	private EditText txtMessage;
	private TextView lblTitle;
	private TextView lblStatus;
	private ProgressBar pgrStatus;
	private Button btnPreviousPosts;
	private MenuItem miExit;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        lblTitle = (TextView) findViewById(R.id.lblTitle);
        txtMessage = (EditText) findViewById(R.id.txtMessage);
        pnlPosts = (LinearLayout) findViewById(R.id.pnlPosts);
        lblStatus = (TextView) findViewById(R.id.lblStatus);
        pgrStatus = (ProgressBar) findViewById(R.id.pgrStatus);
        btnPreviousPosts = (Button) findViewById(R.id.btnPreviousPosts);
        initData();
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	boolean b = super.onCreateOptionsMenu(menu);
    	miExit = menu.add(getString(R.string.exit));
    	miExit.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
			
			@Override
			public boolean onMenuItemClick(MenuItem arg0) {
				finish();
				return true;
			}
		});
		return b;
    }
    
    @Override
    protected void onDestroy() {
    	super.onDestroy();
    	storeUserData();
    	db.close();
    }

	private void initData() {
		try {
        	initSubscription();
        	update();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void initSubscription() throws IOException {
		List<Subscription> subscriptions = subscriptionDAO.list();
		if (subscriptions.isEmpty()) {
			new AlertDialog.Builder(this)
					.setTitle("Bạn mới bắt đầu sử dụng?")
					.setMessage("Mời nhập thông tin về diễn đàn bạn muốn theo dõi.")
					.create().show();
			Intent intent = new Intent(this, SubscriptionEditor.class);
			startActivityForResult(intent, CREATE_FIRST_SUBSCRIPTION);
		} else {
			subscription = subscriptions.get(0);
			forumAdapter.login(subscription.getUserName(), subscription.getPassword(), 
					subscription.getThread().getBaseUrl());
			lblTitle.setText(subscription.getThread().getTitle());
		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == CREATE_FIRST_SUBSCRIPTION) {
			initData();
		}
	}

	private void update() {
		new UpdateTask().execute();
	}

	private int indexOfPost(String postId, List<Post> posts) {
		for (int i = 0; i < posts.size(); i++) {
			if (postId.equals(posts.get(i).getPostId())) {
				return i;
			}
		}
		return -1;
	}

	public void onUpdate(View view) {
		subscription.setLastReadPostId(lastPostId);
		update();
	}
	
	public void onShowPreviousPosts(View view) {
		try {
			prependPosts(forumAdapter.getPostsOfPage(subscription.getThread(), firstPage-1));
			firstPage--;
			if (firstPage <= 1) {
				btnPreviousPosts.setVisibility(View.GONE);
			}
		} catch (IOException e) {
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
			e.printStackTrace();
		} catch (ParseException e) {
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
			e.printStackTrace();
		}
	}

	private void prependPosts(List<Post> posts) {
		for (ListIterator<Post> it = posts.listIterator(); it.hasPrevious();) {
			Post post = (Post) it.previous();
			pnlPosts.addView(createRuler(), 0);
			PostView postView = new PostView(this, post);
			postView.setRead(true);
			pnlPosts.addView(postView, 0);
		}
	}

	public void onSubmit(View view) {
		Post newPost = new Post("", "", new Date(), "", txtMessage.getText().toString());
		if (forumAdapter.submitPost(newPost, subscription.getThread())) {
			update();
		}
	}

	private LinearLayout appendPost(Post post) {
		if (pnlPosts.getChildCount() > 0) {
			pnlPosts.addView(createRuler());
		}
		PostView postView = new PostView(this, post);
    	postView.setOnTouchListener(postTouchListener);
    	pnlPosts.addView(postView);
    	return postView;
    }

	private View createRuler() {
		View ruler = new View(this);
		ruler.setLayoutParams(new LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
		ruler.setMinimumHeight(5);
		ruler.setBackgroundDrawable(
				getResources().getDrawable(R.drawable.ruler));
		return ruler;
	}

	private void storeUserData() {
		subscriptionDAO.update(subscription);
    	threadDAO.update(subscription.getThread());
	}

	private View.OnTouchListener postTouchListener = new View.OnTouchListener() {
		
		@Override
		public boolean onTouch(View view, MotionEvent event) {
			PostView postView = (PostView) view;
			if (!postView.isRead()) {
				for (int i = 0; i < pnlPosts.getChildCount(); i++) {
					View child = pnlPosts.getChildAt(i);
					if (child instanceof PostView) {
						PostView prevPostView = (PostView) child;
						if (prevPostView == postView) {
							break;
						}
						prevPostView.setRead(true);
					}
				}
				subscription.setLastReadPostId(postView.getPost().getPostId());
			}
			return true;
		}
	};

	private class UpdateTask extends AsyncTask<Void, List<Post>, Void> implements PostLoadingCallback {
		
		private boolean firstNewPost = true; 
		
		@Override
		protected Void doInBackground(Void... params) {
			try {
				if (subscription == null) {
					return null;
				}
				if (subscription.getLastReadPostId() == null) {
					forumAdapter.getAllPosts(subscription.getThread(), this);
				} else {
					int page = Math.max(subscription.getThread().getPageCount(), 1);
					List<Post> newPosts = forumAdapter.getPostsOfPage(subscription.getThread(), page);
					int index = indexOfPost(subscription.getLastReadPostId(), newPosts);
					if (index < 0 && subscription.getThread().getPageCount() > 1) { 
						// give it another chance
						newPosts = new ArrayList<Post>();
						page = 1;
						while (index < 0 && page < subscription.getThread().getPageCount()) {
							newPosts.addAll(forumAdapter.getPostsOfPage(subscription.getThread(), page));
							index = indexOfPost(subscription.getLastReadPostId(), newPosts);
						}
					}
					if (index >= 0) {
						newPosts.subList(0, index+1).clear();
					}
					
					appendPosts(newPosts);
					if (page < subscription.getThread().getPageCount()) {
						forumAdapter.getPostsFromPage(subscription.getThread(), page+1, this);
					}
					
					if (firstPage < 0) {
						firstPage = page;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ParseException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPreExecute() {
			lblStatus.setText("Đang lấy dữ liệu...");
			pgrStatus.setVisibility(View.VISIBLE);
		}
		
		@Override
		protected void onPostExecute(Void result) {
			if (firstPage > 1) {
				btnPreviousPosts.setVisibility(View.VISIBLE);
			}
			lblTitle.setText(subscription.getThread().getTitle());
			lblStatus.setText("Xong.");
			pgrStatus.setVisibility(View.INVISIBLE);
		}

		@Override
		protected void onProgressUpdate(List<Post>... postLists) {
			List<Post> posts = postLists[0];
			appendPosts(posts);
			lastPostId = posts.get(posts.size()-1).getPostId();
		}
		
		@SuppressWarnings("unchecked")
		@Override
		public void postsLoaded(List<Post> posts) {
			publishProgress(posts);
		}		

		private void appendPosts(List<Post> posts) {
			if (posts.size() > 0) {
				pnlPosts.removeView(findViewById(R.id.lblEmpty));
				for (Post post : posts) {
					View postView = appendPost(post);
					if (firstNewPost) {
						postView.requestFocus();
						firstNewPost = false;
					}
				} // end of for
			} // end of if
		}
	}
	
}